/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Commons;

import Commons.Logging.Log;
import Commons.Logging.Logger;
import Manager.TQProxyFactory;
import Manager.WorkerNetwork;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.SocketException;
import Manager.TQueueManagerProxy;
import java.io.File;
import java.net.InetAddress;
import java.util.logging.Level;


/**Questa classe descrive l'Activity
 *
 * @author Team5
 */
public class Activity implements Runnable{

    //Attributes
    private Workflow wf;
    private String id;
    private WorkerNetwork sbn;
    private TQueueManagerProxy wkProxy;
    private Logger l;

    //Operations

    /** Metodo costruttore della classe
     *
     */
    public Activity() {
        id=this.getClass().getSimpleName()+this.hashCode();
        l=new Logger("log"+id+".xml",this.getClass().getSimpleName());
    }

    public Activity(Logger l) {
        id=this.getClass().getSimpleName()+this.hashCode();
        this.l = l;
    }

    /** Il metodo restituisce il workflow dell'attività
     *
     * @return il workflow restituito
     */
    public Workflow getWf() {
        return wf;
    }

    /** Il metodo permette di impostare
     * il workflow relativo all'attività
     *
     * @param val oggetto della classe WorkFlow
     */
    public void setWf(Workflow val) {
        wf = val;
        l.merge(wf.getVectorClock());
    }

    /** Il metodo restituisce la WorkerNetwork dell'attività
     *
     * @return la WorkerNetwork restituita
     */
    public WorkerNetwork getSbn() {
        return sbn;
    }

    /** Il metodo permette di impostare il valore
     * della WorkerNetwork relativa all'attività
     *
     * @param val oggetto della classe WorkerNetwork
     */
    public void setSbn(WorkerNetwork val) {
        sbn = val;
    }

    /** Questo metodo permette di schedulare l'attività.
     *
     */
    public void scheduleActivity() {

        Thread t= new Thread(this);
        t.start();
    
    }

    /** Il metodo restituisce il proxy del worker relativo all'attività
     *
     * @return il proxy restituito
     */
    public TQueueManagerProxy getWkProxy(){
        return wkProxy;
    }

    /** Il metodo permette di impostare il valore
     * del proxy del worker relativo all'attività
     *
     * @param val oggetto della classe TQueueManagerProxy
     */
    public void setWkProxy(TQueueManagerProxy val) {
        wkProxy = val;
    }

    /** Questo metodo esegue la schedulazione dell'attività
     *
     */
    public void run() {

    TQProxyFactory tqpf=new TQProxyFactory();
    //RECUPERO IL PROXY DA TQPF
    try{
    wkProxy=tqpf.getProxy();
    
    //serviranno successivamente nella fase di monitoraggio
    //this.getWf();
    //this.getSbn();

    TaskDescriptor td;
    Address addr=new Address();

    
    for(int i=0;i<wf.getTasks().size();i++){
        td=wf.getTask(i);
        
        
        
         addr=sbn.getWorker(i);
         //COMMENTATO PERCHE' NON FUNZIONA
              if(td.getLink()!=null)
         {

              System.out.println("ACTIVITY: sto inviando il file...al worker:  "+InetAddress.getByName(addr.getIP()));
              l.logging(new Log(this.getClass().getSimpleName(), id, "invio file al Worker ", String.valueOf(System.currentTimeMillis())));
              SendFile invia = new SendFile(td.getLink()+"-"+wf.getID()+"-"+td.getID(),td.getLink(),InetAddress.getByName(addr.getIP()));
              Thread t1 = new Thread(invia);
              t1.start();

         }
        
        
        
        
        wkProxy.setAddr(addr);
        l.logging(new Log(this.getClass().getSimpleName(), id, "invio TD: " + td.toString(), String.valueOf(System.currentTimeMillis())));
        td.setVectorClock(l.getVectorClock());
        int x=wkProxy.enqueue(td);

       
  
        
        
        
    }
        } catch (SocketException ex) {
            java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
        }  catch (InterruptedException ex) {
            java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }

    class SendFile implements Runnable
    {
          
        private String vecchioNome;
        private String nuovoNome;
        InetAddress indirizzoWorker;
        public SendFile(String vecchioNome,String nuovoNome, InetAddress indirizzoWorker) throws SocketException, IOException, FileNotFoundException, InterruptedException {
                this.vecchioNome=vecchioNome;
                this.nuovoNome=nuovoNome;
                this.indirizzoWorker=indirizzoWorker;

      }

        public void run() {
                 ClientTrasferimentoFileUDP client = new ClientTrasferimentoFileUDP(indirizzoWorker,Indirizzi.portaRicezioneFileWorker,"Download/"+vecchioNome,nuovoNome);
                 client.configuraBuffers(4, 1024);

                 boolean inviato=false;
                 while(!inviato)
                 {
                         try {
                                    System.out.println("run() "+this.toString());
                                    l.logging(new Log(this.getClass().getSimpleName(), id, "Avviato run() di Activity", String.valueOf(System.currentTimeMillis())));
                                    File file =  new File(vecchioNome);
                                    client.invioFileRemotoUDP();
                                    inviato=true;
                                    break;
                              }
                         
                         catch (SocketException ex) {
                                        java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
                         } catch (IOException ex) {
                                        java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
                         }  catch (InterruptedException ex) {
                                        java.util.logging.Logger.getLogger(Activity.class.getName()).log(Level.SEVERE, null, ex);
                         }
                           catch (NullPointerException  ex)
                                {
                                    System.out.println("File Non Ancora Ricevuto.");
                             
                              }

               }

        }
        @Override
        public String toString(){
        return "Activity:(Nuovo nome:" + this.nuovoNome +")";

        }

    }
}
